package dao

import (
	"context"
	"errors"
	"github.com/qiniu/qmgo"
	"github.com/sirupsen/logrus"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"monoblog/config"
	"monoblog/domain/dto"
	"monoblog/domain/model"
	"strconv"
	"sync"
)

var (
	userRepo *UserRepository // 单例实例存储变量
	once6    sync.Once       // 确保初始化只执行一次的同步工具
)

// 初始化 QMGO 集合（单例模式）
func NewUserRepository() *UserRepository {
	once6.Do(func() { // 并发安全的初始化逻辑，只会执行一次
		userRepo = &UserRepository{
			collection: config.GetDataBase().Collection(model.UserCollectionName), //指定集合名称
			ctx:        context.Background(),
		}
	})
	return userRepo // 返回唯一实例
}

type UserRepository struct {
	collection *qmgo.Collection // QMGO 集合对象（替代原生 mongo.Collection）
	ctx        context.Context  // 上下文（用于数据库操作超时控制）
}

func (impl UserRepository) Add(user *model.WebUser) error {
	// 取自增ID
	id, _ := NewAutoIDSequenceDao().NextID(model.UserCollectionName)
	user.ID = id

	_, err := impl.collection.InsertOne(impl.ctx, user)
	return err
}

func (impl UserRepository) DeleteById(id int64) error {
	// 执行删除操作
	err := impl.collection.RemoveId(impl.ctx, id)
	if errors.Is(err, mongo.ErrNoDocuments) {
		logrus.Warnf("record not found. dont delete. id: %v", id)
		return nil
	}
	return err
}

func (impl UserRepository) ExistsByUsername(username string) (bool, error) {
	n, err := impl.collection.Find(impl.ctx, qmgo.M{"username": username}).Count()
	return n > 0, err
}

func (impl UserRepository) ExistsByPhone(phone string) (bool, error) {
	n, err := impl.collection.Find(impl.ctx, qmgo.M{"phone": phone}).Count()
	return n > 0, err
}

func (impl UserRepository) ExistsByEmail(email string) (bool, error) {
	n, err := impl.collection.Find(impl.ctx, qmgo.M{"email": email}).Count()
	return n > 0, err
}

func (impl UserRepository) FindByID(id int64) (*model.WebUser, error) {
	var user model.WebUser

	err := impl.collection.Find(impl.ctx, qmgo.M{"_id": id}).One(&user)

	if errors.Is(err, mongo.ErrNoDocuments) {
		logrus.Warnf("record not found. id: %v", id)
		return nil, errors.New("找不到数据, id: " + strconv.FormatInt(id, 10))
	}
	return &user, err
}

func (impl UserRepository) FindByUserId(userId string) (*model.WebUser, error) {
	var user model.WebUser

	// userId 作为 username 查询
	err := impl.collection.Find(impl.ctx, qmgo.M{"username": userId}).One(&user)

	if errors.Is(err, mongo.ErrNoDocuments) {
		logrus.Warnf("record not found. username: %v", userId)
		return nil, errors.New("找不到数据, username: " + userId)
	}
	return &user, err
}

func (impl UserRepository) FindListByPhone(phone string) ([]*model.WebUser, error) {
	var users = make([]*model.WebUser, 0)

	err := impl.collection.Find(impl.ctx, qmgo.M{"phone": phone}).
		Select(bson.M{"password": 0}).All(&users)

	return users, err
}

func (impl UserRepository) FindListByEmail(email string) ([]*model.WebUser, error) {
	var users = make([]*model.WebUser, 0)

	err := impl.collection.Find(impl.ctx, qmgo.M{"email": email}).
		Select(bson.M{"password": 0}).All(&users)

	return users, err
}

func (impl UserRepository) FindList(query dto.UserQuery) ([]*model.WebUser, int, error) {
	var users = make([]*model.WebUser, 0)

	filter := bson.M{} // 构建查询条件：空条件

	if query.UserId != "" {
		filter["userId"] = query.UserId
		query.Keyword = ""
	}
	if query.Phone != "" {
		filter["phone"] = query.Phone
		query.Keyword = ""
	}
	if query.Email != "" {
		filter["email"] = query.Email
		query.Keyword = ""
	}
	if query.Nickname != "" {
		filter["nickname"] = qmgo.M{"$regex": "^" + query.Keyword} // 前缀匹配（以关键词开头）
		query.Keyword = ""
	}
	if query.Status != 0 {
		filter["status"] = query.Status
		query.Keyword = ""
	}

	if len(query.UserIds) > 0 {
		// userId 作为 username 查询
		filter["username"] = bson.M{"$in": query.UserIds}
	}
	if len(query.Roles) > 0 {
		filter["roles"] = bson.M{"$in": query.Roles}
	}
	if query.Keyword != "" {
		//关键字搜索，支持user账号、手机号、邮箱、昵称
		filter["$or"] = []qmgo.M{
			{"username": query.Keyword},                      // 等值匹配user账号（精确匹配）
			{"phone": qmgo.M{"$regex": "^" + query.Keyword}}, // 前缀匹配手机号（以关键词开头）
			{"email": qmgo.M{"$regex": "^" + query.Keyword}}, // 前缀匹配邮箱（以关键词开头）
			{"nickname": qmgo.M{"$regex": query.Keyword}},    // 模糊搜索昵称（包含关键词）
		}
	}

	var total int
	if !query.IsZero() {
		//查询条数
		n, _ := impl.collection.Find(impl.ctx, filter).Count()
		total = int(n)
	}

	//select字段
	exceptColumns := bson.M{"password": 0}
	if query.IsLite {
		exceptColumns["profile"] = 0
	}
	//分页查询
	err := impl.collection.Find(impl.ctx, filter).
		Select(exceptColumns).
		Sort(query.SortField()). //排序字段
		Skip(int64(query.Offset())).Limit(int64(query.Limit())).
		All(&users)
	return users, total, err
}
